module rx_top #(
	parameter CLK_FREQ = 50_000_000 ,
	parameter BAUD_RATE = 9600 ,
	parameter PARITY = "NONE" ,
	parameter DATA_FRAME_WIDTH = 8 
)(
	input wire 		clk ,
	input wire 		rst_n ,
	input wire 		uart_rx ,
	output logic [DATA_FRAME_WIDTH-1:0] data_frame_rx ,
	output logic 	rx_done ,
	output logic 	error  //frame error
);
	localparam 	IDLE  		= 5'b00_000 ,
				START_BIT 	= 5'b00_001 ,//开始位
				DATA_FRAME 	= 5'b00_010 ,//移位输出
				PARITY_BIT 	= 5'b00_100 ,//校验位
				STOP_BIT 	= 5'b01_000 ,//停止位
				DONE 		= 5'b10_000 ;
	logic [4:0] c_sta , n_sta ;


	logic sample_clk ;
	logic baud_rate_clk ;
	logic frame_en ;
	logic cnt_en ;
	logic [3 :0 ] sample_clk_cnt ;
	logic [$clog2(DATA_FRAME_WIDTH)-1 : 0 ] sample_bit_cnt ;

	/**********是否有校验位***********/
	logic [1:0] verify_mode ;
	generate
		if(PARITY == "ODD")begin
			assign verify_mode = 2'b01 ;
		end else if (PARITY == "EVEN") begin
			assign verify_mode = 2'b10 ;
		end else begin
			assign verify_mode = 2'b00 ;
		end
	endgenerate
	/**********是否有校验位***********/


	logic uart_rx0 , uart_rx1 , uart_rx2 , uart_rx3 ; //为了顺利采集到起始位
	always_ff @(posedge clk or negedge rst_n) begin : proc_uart_rx_Reg_Seq 
		if(~rst_n)begin
			uart_rx0 <= 0 ;
			uart_rx1 <= 0 ;
			uart_rx2 <= 0 ;
			uart_rx3 <= 0 ;
		end else begin
			uart_rx0 <= 0 ;
			uart_rx1 <= uart_rx0 ;
			uart_rx2 <= uart_rx2 ;
			uart_rx3 <= uart_rx3 ;
		end
	end

	//negedge of the uart rx ----start_bit
	assign frame_en = ~uart_rx0 & ~uart_rx1 & uart_rx2 & uart_rx3 ;

	always_ff @(posedge  clk or negedge rst_n) begin : proc_cnt_en 
		if(~rst_n )begin
			cnt_en <= 1'b0 ;
		end else begin
			if(frame_en == 1'b1 ) begin
				cnt_en <= 1'b1 ;
			end else if ( rx_done )begin
				cnt_en <= 1'b0 ;
			end else begin
				cnt_en <= cnt_en;
			end
		end
	end
	assign baud_rate_clk = sample_clk & sample_clk_cnt == 4'd8 ;

	always_ff @(posedge clk or negedge rst_n) begin : proc_sammple_clk_cnt 
		if(~rst_n) begin	
			sample_clk_cnt <= 'd0 ;
		end else if(cnt_en)begin
			if (baud_rate_clk)begin
				sample_clk_cnt <= 4'd0 ;
			end else if(sample_clk )begin
				sample_clk_cnt <= sample_clk_cnt + 1'b1 ;
			end else begin
				sample_clk_cnt <= sample_clk_cnt ;
			end
		end
	end

	logic		[1:0]	sample_result	;
	always_ff @(posedge clk or negedge rst_n) begin : proc_saple_result
		if (~rst_n) 
			sample_result <= 1'b0;
		else if (sample_clk) begin
			case (sample_clk_cnt)
				4'd0:sample_result <= 2'd0;
				4'd3,
				4'd4,
				4'd5: sample_result <= sample_result + uart_rx;
				default: sample_result <= sample_result;
			endcase
		end
	end


	//FSM
	always @(*) begin
		case(c_sta)
			IDLE : n_sta = frame_en ? START_BIT : IDLE ;
			START_BIT : n_sta = (baud_rate_clk & sample_result[1]==1'b0) ?  DATA_FRAME : START_BIT ;
			DATA_FRAME : begin	
				case(^verify_mode)
					1'b1 : n_sta = (sample_bit_cnt == DATA_FRAME_WIDTH & baud_rate_clk ) ? PARITY_BIT : DATA_FRAME ;
					1'b0 : n_sta = (sample_bit_cnt == DATA_FRAME_WIDTH & baud_rate_clk ) ? STOP_BIT   : DATA_FRAME ;
					default: n_sta = (sample_bit_cnt == DATA_FRAME_WIDTH & baud_rate_clk ) ? STOP_BIT : DATA_FRAME ;
				endcase // ^verify_mode
			end
			PARITY_BIT : n_sta = baud_rate_clk ? STOP_BIT : PARITY_BIT ;
			STOP_BIT : n_sta = (baud_rate_clk & sample_result[1] == 1'b1) ? DONE : STOP_BIT ;
			DONE : n_sta = IDLE ;
			default : begin  n_sta = IDLE ; end
		endcase // c_stadcase
	end
	always @(posedge clk or negedge rst_n) begin
	if (!rst_n) begin
		data_frame_rx	<= 'd0;
		rx_done		<= 1'b0;
		error	<= 1'b0;
	end else begin
		case (n_sta)
			IDLE		: begin
							data_frame_rx	<= 'd0;
							rx_done		<= 1'b0;
							error	<= 1'b0;
						end 
			START_BIT	: begin
							data_frame_rx	<= 'd0;
							rx_done		<= 1'b0;
							error	<= 1'b0;
						end 
			DATA_FRAME	: begin
							if (sample_clk & sample_clk_cnt == 4'd6) 
								data_frame_rx <= {sample_result[1],data_frame_rx[DATA_FRAME_WIDTH-1:1]};
							else
								data_frame_rx	<= data_frame_rx;
							rx_done		<= 1'b0;
							error	<= 1'b0;
						end 
			PARITY_BIT	: begin
							data_frame_rx	<= data_frame_rx;
							rx_done		<= 1'b0;
							if (sample_clk_cnt == 4'd8)
							error	<= ^data_frame_rx ^ sample_result[1];
							else
							error	<= error;
						end 
			STOP_BIT	: begin
							data_frame_rx	<= data_frame_rx;
							rx_done		<= 1'b0;
							error	<= error;
						end 
			DONE		: begin
							error	<= error;
							rx_done		<= 1'b1;
							data_frame_rx	<= data_frame_rx;
						end 
			default: begin
							data_frame_rx	<= data_frame_rx;
							rx_done		<= 1'b0;
							error	<= error;
						end 
		endcase
	end
	end

	rx_bps_clk_gen #(
			.CLK_FREQ(CLK_FREQ),
			.BAUD_RATE(BAUD_RATE)
		) inst_rx_bps_clk_gen (
			.clk        (clk),
			.rst_n      (rst_n),
			.rx_start   (frame_en),
			.rx_done    (rx_done),
			.sample_clk (sample_clk)
		);

endmodule // rx_top